﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using BrightIdeasSoftware;
using NymphsLib.CommonUtilities;
using MovieBrowser.Controller;
using MovieBrowser.Event;
using MovieBrowser.Model;
using MovieBrowser.Presentation.Events;
using MovieBrowser.Presentation.Forms;
using MovieBrowser.Presentation.Forms.Db;
using MovieBrowser.Presentation.Forms.Dialogs;
using MovieBrowser.Util;

namespace MovieBrowser.Presentation.List
{
    public partial class MoviesListView : UserControl, IMovieList, IDebugLogEvent
    {
        readonly SaveFileDialog _saveFileDialog = new SaveFileDialog();
        public MovieBrowserController Controller { get; set; }

        #region Events
        public event EventHandler MovieSelectionChange;
        public event EventHandler CopyMovies;
        public event EventHandler Enqueue;
        public event EventHandler DebugText;
        //
        public void InvokeOnDebugText(Exception exception)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(exception));
        }
        public void InvokeOnDebugText(string text)
        {
            var handler = DebugText;
            if (handler != null) handler(this, new DebugTextEventArgs(text));
        }
        //
        public void InvokeOnMovieSelectionChange(EventArgs e)
        {
            var handler = MovieSelectionChange;
            if (handler != null) handler(this, e);
        }
        //
        public void InvokeCopyMovies(CopyMoviesEventArgs e)
        {
            var handler = CopyMovies;
            if (handler != null) handler(this, e);
        }
        //
        public void InvokeEnqueue(CopyMoviesEventArgs e)
        {
            EventHandler handler = Enqueue;
            if (handler != null) handler(this, e);
        }
        #endregion

        public MoviesListView()
        {
            InitializeComponent();
            movieListView.Font = Properties.Settings.Default.ListFont;

            olvColCreationDate.AspectToStringFormat = "{0:dd/MM/yyyy}";
            olvColumnReleaseDate.GroupKeyGetter = delegate(object rowObject)
            {
                var song = (Movie)rowObject;
                if (song.ReleaseDate != null)
                    return new DateTime(((DateTime)song.ReleaseDate).Year, ((DateTime)song.ReleaseDate).Month, 1);
                return null;
            };
            olvColumnReleaseDate.GroupKeyToTitleConverter = delegate(object groupKey)
            {
                if (groupKey != null)
                    return ((DateTime)groupKey).ToString("MMMM, yyyy");
                return null;
            };
        }

        private void TbRefreshDbClick(object sender, EventArgs e)
        {
            LoadMovies();
        }

        private void TbUpdateDbClick(object sender, EventArgs e)
        {
            new UpdateMovieInformation(movieListView.SelectedItems.ToIList()).Show();
        }

        private void TbDeleteFromDbClick(object sender, EventArgs e)
        {
            DeleteMovies();
        }

        private void DeleteMovies()
        {
            if (MessageBox.Show("Sure to delete selected movie?", "Confirm Delete", MessageBoxButtons.YesNoCancel) ==
                DialogResult.Yes)
            {
                foreach (OLVListItem item in movieListView.SelectedItems)
                {
                    Controller.RemoveMovie(((Movie)item.RowObject).ImdbId);
                    movieListView.RemoveObject(item.RowObject);
                    movieListView.Items.Remove(item);
                }
            }
        }

        private void TbExportToExcelClick(object sender, EventArgs e)
        {
            _saveFileDialog.Filter = @"Excel Document|*.xlsx";
            if (_saveFileDialog.ShowDialog(this) != DialogResult.OK) return;

            var newFile = new FileInfo(_saveFileDialog.FileName);
            Controller.SaveToExcel(newFile, (from o in Controller.Db.Movies orderby o.Title select o).ToList());
        }

        private void TbUpdateKeywordsClick(object sender, EventArgs e)
        {
            Controller.UpdateKeywords(SelectedMovies);
        }

        private void TbWantToWatchClick(object sender, EventArgs e)
        {
            tbWantToWatch.Checked = !tbWantToWatch.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                if (Authorization.IsAuthorized)
                {

                    Controller.ToggleOrSetWishlist(Authorization.LoggedInUser, movie, tbWantToWatch.Checked);
                }
            }
        }


        private void TbLikeItClick(object sender, EventArgs e)
        {
            tbLikeIt.Checked = !tbLikeIt.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                if (Authorization.IsAuthorized)
                {

                    Controller.SetFavourite(Authorization.LoggedInUser, movie, tbLikeIt.Checked);
                }
            }
        }

        private void TbDislikeItClick(object sender, EventArgs e)
        {
            tbDislikeIt.Checked = !tbDislikeIt.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                if (Authorization.IsAuthorized)
                {

                    Controller.SetFavourite(Authorization.LoggedInUser, movie, tbDislikeIt.Checked);
                }
            }
        }

        private void TbSeenItClick(object sender, EventArgs e)
        {
            tbSeenIt.Checked = !tbSeenIt.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                if (Authorization.IsAuthorized)
                {

                    Controller.ToggleOrSetSeenIt(Authorization.LoggedInUser, movie, tbSeenIt.Checked);
                }
            }
        }

        private void TbHaveItClick(object sender, EventArgs e)
        {
            tbHaveIt.Checked = !tbHaveIt.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                if (Authorization.IsAuthorized)
                {

                    Controller.ToggleOrSetHaveIt(Authorization.LoggedInUser, movie, tbHaveIt.Checked);
                }
            }
        }

        private void TbUpdatedClick(object sender, EventArgs e)
        {
            tbUpdated.Checked = !tbUpdated.Checked;
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                var movie1 = movie;
                var m = Controller.Db.Movies.Where(o => o.ImdbId == movie1.ImdbId).FirstOrDefault();
                if (m == null) continue;
                m.IsUpdated = tbUpdated.Checked;
                movie.IsUpdated = tbUpdated.Checked;
                Controller.Db.SaveChanges();
            }
        }

        private void SearchTextBoxSearchStarted(object sender, EventArgs e)
        {
            ComponentUtility.TimedFilter(movieListView, searchTextBox.Text);
        }

        private void SearchTextBoxSearchCancelled(object sender, EventArgs e)
        {
            ComponentUtility.TimedFilter(movieListView, "");
        }

        private void DataListViewSelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                var movie = (Movie)(movieListView.SelectedObject);
                if (movie == null) return;
                var eventArgs = new MovieEventArgs(movie, "SelectionChanged");
                InvokeOnMovieSelectionChange(eventArgs);
            }
            catch (Exception exception)
            {
                Logger.Exception(exception, 184);
                InvokeOnDebugText(exception);
            }
        }


        private void DataListViewDoubleClick(object sender, EventArgs e)
        {
            Controller.SearchMovie(MovieBrowserController.ImdbSearch, (Movie)(movieListView.SelectedObject));
        }

        private void DataListViewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
                Controller.SearchMovie(MovieBrowserController.ImdbSearch, (Movie)(movieListView.SelectedObject));
            else if (e.KeyCode == Keys.Delete)
                DeleteMovies();
        }

        public void LoadMovies()
        {
            Controller.Refresh();
            var movies = Controller.Movies;
            if (Authorization.IsAuthorized)
            {
                foreach (var movie in movies)
                {
                    Movie movie1 = movie;
                    var pn = Controller.Db.MoviePersonalNotes.FirstOrDefault(o => o.Movie.Id == movie1.Id && o.User.Id == Authorization.LoggedInUser.Id);
                    if (pn != null)
                    {
                        movie.Seen = pn.Seen;
                        movie.Have = pn.Have;
                        movie.Watchlist = pn.Wishlist;
                    }

                    var cc = Controller.Db.MovieKeyValues.Where(o => o.Movie.Id == movie1.Id && o.Key == "Subtitle").FirstOrDefault();
                    if (cc != null)
                        movie.Subtitle = Convert.ToBoolean(cc.Value);
                }
            }
            movieListView.DataSource = movies;

        }

        public void UpdateNode(Movie movie)
        {
            Controller.UpdateMovieNode(SelectedMovie, movie);
        }

        public Movie SelectedMovie { get { return movieListView.SelectedObject as Movie; } }

        public IList<Movie> SelectedMovies { get { return movieListView.SelectedObjects.Cast<Movie>().ToList(); } }

        private void TbUpdateNodesClick(object sender, EventArgs e)
        {
            Controller.UpdateInformation(SelectedMovies, new MovieBrowserController(Controller));
        }

        private void TbFixInformationClick(object sender, EventArgs e)
        {
            foreach (var movie in Controller.Db.Movies)
            {
                Movie movie1 = movie;
                var filesystem = Controller.Db.MovieFilesystems.Where(o => o.Movie.Id == movie1.Id).Count();
                movie.IsInCollection = filesystem > 0;
            }

            foreach (var movieFilesystem in Controller.Db.MovieFilesystems)
            {
                var path = movieFilesystem.FolderPath;

                string computername;
                if (path.StartsWith("\\\\"))//Network
                {

                    computername = path.Substring(2);
                    computername = computername.Substring(0, computername.IndexOf("\\"));
                }
                else
                {
                    computername = movieFilesystem.ComputerName;
                }
                movieFilesystem.ComputerName = computername;
            }
            Controller.Db.SaveChanges();

            LoadMovies();
        }

        private void DataListViewFormatRow(object sender, BrightIdeasSoftware.FormatRowEventArgs e)
        {
            ComponentUtility.FormatRow(movieListView, e);
        }

        private void TbDbInfoClick(object sender, EventArgs e)
        {
            if (SelectedMovie != null)
                new MovieUpdateForm(Controller.Db, SelectedMovie).Show(this);
        }

        private void TbCopyMoviesClick(object sender, EventArgs e)
        {
            OnCopyMovie();
        }

        private void CopyMovieToolStripMenuItemClick(object sender, EventArgs e)
        {
            OnCopyMovie();
        }

        private void OnCopyMovie(bool enqueue = false)
        {
            var movies = new List<Movie>();
            foreach (Movie movie in movieListView.SelectedObjects)
            {
                var movie1 = movie;
                var filesystems = Controller.Db.MovieFilesystems.Where(o => o.Movie.Id == movie1.Id).ToList();
                switch (filesystems.Count)
                {
                    case 1:
                        movie.FilePath = filesystems[0].FolderPath;
                        movies.Add(movie);
                        break;
                    case 0:
                        continue;
                    default:
                        {
                            var selectMovie = new SelectMovie(movie, filesystems);

                            selectMovie.ShowDialog(this);
                            if (String.IsNullOrEmpty(selectMovie.SelectedLocation)) continue;
                            movie.FilePath = selectMovie.SelectedLocation;
                            movies.Add(movie);
                        }
                        break;
                }
            }
            if (movies.Count > 0)
            {
                if (enqueue)
                {
                    InvokeEnqueue(new CopyMoviesEventArgs(movies));
                }
                else
                {
                    InvokeCopyMovies(new CopyMoviesEventArgs(movies));
                }
            }
        }

        private void AddToQueueToolStripMenuItemClick(object sender, EventArgs e)
        {
            OnCopyMovie(true);
        }

        private void TbEnqueueClick(object sender, EventArgs e)
        {
            OnCopyMovie(true);
        }

        public void ShowGroup(bool group)
        {
            movieListView.ShowGroups = group;
        }

        public void UpdateFont(System.Drawing.Font font)
        {
            movieListView.Font = font;
        }
    }
}
